#include "doCCL.h"

#include <cv.h>
#include <highgui.h>
#include <iomanip>
#include <iostream>
#include <math.h>
#include <sys/timeb.h>
#include <time.h>
#include "stdio.h"
#include <cutil_inline.h> 
#include <iostream>
#define DEBUG
#ifdef DEBUG
#define MY_SAFE_CALL(x) cutilSafeCall(x)
#else
#define MY_SAFE_CALL(x) x
#endif




int main(int argc, char** argv)
{
    if (argc < 2)
    {
        std::cout << "Usage: " << argv[0] << " <input.png>"  << std::endl;
        exit(1);
    }

    IplImage* input_image = NULL;
	input_image = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
    if(!input_image)
    {
        std::cout << "ERROR: Failed to load input image" << std::endl;
        return -1;
    }

	int width = input_image->width;
    int height = input_image->height;
    int bpp = input_image->nChannels;
//get the input image
    IplImage* im_binary = cvCreateImage(cvGetSize(input_image),8,1);
    unsigned int* im_binary2 = (unsigned int *)malloc(width*height*sizeof(unsigned int));
    //apply thresholding
    cvThreshold(input_image, im_binary, 128, 1, CV_THRESH_BINARY_INV);
   //converting the image to unsigned int
    for (int y=0;y<height;y++)
    {
      printf("\n");
      for (int x=0;x<width;x++)
      {
	im_binary2[y*width+x]=im_binary->imageData[y*width+x];
      }
    }
     im_binary2[0]=1;
     im_binary2[(height-1)*width]=1;
     
#define PRINT_INPUT
# ifdef PRINT_INPUT 
    printf("printing input image \n");
    for (int y=0;y<height;y++)
    {
      printf("\n");
      for (int x=0;x<width;x++)
      {
	printf("%d",im_binary2[y*width+x]);
      }
    }
    printf("\n");
#endif
  //create the array to hold the final labels
    int* labels_final = new int[width * height];

    //allocate space for the image in the device
    unsigned int * Labels_gpu = NULL;
    MY_SAFE_CALL(cudaMalloc((void **)(&Labels_gpu), (width * height) * sizeof(unsigned int)));

  
    

    //initialize pointers and variables for the algorithm
    int threads_x,threads_y;
    threads_x=threads_y=16;
//copying the data to the device
MY_SAFE_CALL(cudaMemcpy(Labels_gpu,im_binary2,(width * height) * sizeof(unsigned int), cudaMemcpyHostToDevice));
    

    //call kernel here
doCCL(Labels_gpu,width,height,threads_x,threads_y);
//copy from the padded array

	MY_SAFE_CALL(cudaMemcpy(labels_final,Labels_gpu, (width * height) * sizeof(unsigned int), cudaMemcpyDeviceToHost));




    MY_SAFE_CALL(cudaFree(Labels_gpu));
  

#define PRINT_OUTPUT 
 # ifdef PRINT_OUTPUT
   printf("printing output \n");
    for (int y=0;y<height;y++)
    {
      printf("\n");
      for (int x=0;x<width;x++)
      {
	printf("%d \t",labels_final[y*width+x]);
      }
    }
    printf("\n");
   ;
#endif


	return 0;
}
